﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Globalization;

using BizElements.Core;

namespace BizElements.BusinessLayer
{
    /// <summary>
    /// Typed IDbTable class for the table/view 'AppSettings'.
    /// </summary>
    /// <remarks>Table name can be configured in a *.config file. Default is <b>AppSettings</b>. Example:
    /// <code>
    /// <add key="AppSettings.TableName" value="AppSettings"/>
    /// </code>
    /// </remarks>
    [Serializable]
    class AppSettingsMeta : SealedDbTable
    {
        // No custom code: configuration cusomtization is in AppSettingsCatalog class.

        #region Static ctor.

        static AppSettingsMeta()
        {
            ReadSequenceOverrideFromConfig();
            ReadColumnNamesFromConfig();
            ImmutableColumnProperties = CreateImmutableColumnProperties();
            ImmutableTableProperties = CreateImmutableTableProperties();
        }

        #endregion

        #region Configuration.

        static readonly string[] SequenceNameOverrides = new string[12];
        static readonly bool?[] AutoIncrementOverrides = new bool?[12];

        private static void ReadSequenceOverrideFromConfig()
        {
            SequenceNameOverrides[0] = ConfigurationManager.AppSettings["AppSettings.AppSettingId.SequenceName"];
            AutoIncrementOverrides[0] = (SequenceNameOverrides[0] != null) ? (bool?)true : null;
            SequenceNameOverrides[1] = ConfigurationManager.AppSettings["AppSettings.ActorId.SequenceName"];
            AutoIncrementOverrides[1] = (SequenceNameOverrides[1] != null) ? (bool?)true : null;
            SequenceNameOverrides[2] = ConfigurationManager.AppSettings["AppSettings.Application.SequenceName"];
            AutoIncrementOverrides[2] = (SequenceNameOverrides[2] != null) ? (bool?)true : null;
            SequenceNameOverrides[3] = ConfigurationManager.AppSettings["AppSettings.Module.SequenceName"];
            AutoIncrementOverrides[3] = (SequenceNameOverrides[3] != null) ? (bool?)true : null;
            SequenceNameOverrides[4] = ConfigurationManager.AppSettings["AppSettings.Context.SequenceName"];
            AutoIncrementOverrides[4] = (SequenceNameOverrides[4] != null) ? (bool?)true : null;
            SequenceNameOverrides[5] = ConfigurationManager.AppSettings["AppSettings.Component.SequenceName"];
            AutoIncrementOverrides[5] = (SequenceNameOverrides[5] != null) ? (bool?)true : null;
            SequenceNameOverrides[6] = ConfigurationManager.AppSettings["AppSettings.PropertyPathString.SequenceName"];
            AutoIncrementOverrides[6] = (SequenceNameOverrides[6] != null) ? (bool?)true : null;
            SequenceNameOverrides[7] = ConfigurationManager.AppSettings["AppSettings.Value.SequenceName"];
            AutoIncrementOverrides[7] = (SequenceNameOverrides[7] != null) ? (bool?)true : null;
            SequenceNameOverrides[8] = ConfigurationManager.AppSettings["AppSettings.Description.SequenceName"];
            AutoIncrementOverrides[8] = (SequenceNameOverrides[8] != null) ? (bool?)true : null;
            SequenceNameOverrides[9] = ConfigurationManager.AppSettings["AppSettings.ValidFrom.SequenceName"];
            AutoIncrementOverrides[9] = (SequenceNameOverrides[9] != null) ? (bool?)true : null;
            SequenceNameOverrides[10] = ConfigurationManager.AppSettings["AppSettings.ValidUntil.SequenceName"];
            AutoIncrementOverrides[10] = (SequenceNameOverrides[10] != null) ? (bool?)true : null;
            SequenceNameOverrides[11] = ConfigurationManager.AppSettings["AppSettings.Status.SequenceName"];
            AutoIncrementOverrides[11] = (SequenceNameOverrides[11] != null) ? (bool?)true : null;
        }

        static readonly string[] ColumnNames = new string[12];

        private static void ReadColumnNamesFromConfig()
        {
            ColumnNames[0] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "AppSettingId") ?? "AppSettingId";
            ColumnNames[1] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "ActorId") ?? "ActorId";
            ColumnNames[2] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Application") ?? "Application";
            ColumnNames[3] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Module") ?? "Module";
            ColumnNames[4] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Context") ?? "Context";
            ColumnNames[5] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Component") ?? "Component";
            ColumnNames[6] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "PropertyPathString") ?? "PropertyPathString";
            ColumnNames[7] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Value") ?? "Value";
            ColumnNames[8] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Description") ?? "Description";
            ColumnNames[9] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "ValidFrom") ?? "ValidFrom";
            ColumnNames[10] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "ValidUntil") ?? "ValidUntil";
            ColumnNames[11] = AppSettingsCatalog.GetColumnNameOverride("AppSettings", "Status") ?? "Status";
        }

        #endregion

        #region Singleton/immutable configuration objects.

        static readonly DbColumnConfiguration[] ImmutableColumnProperties;
        static readonly DbTableConfiguration ImmutableTableProperties;

        private static DbColumnConfiguration[] CreateImmutableColumnProperties()
        {
            return new DbColumnConfiguration[]
			{
				new DbColumnConfiguration(ColumnNames[0], DbType.Int32, typeof(int), false, 0, true, null, 0, true, false, false, "AppSettingId", int.MinValue, int.MaxValue, false, SequenceNameOverrides[0]),
				new DbColumnConfiguration(ColumnNames[1], DbType.AnsiString, typeof(string), true, 1, AutoIncrementOverrides[1] ?? false, null, 50, false, false, false, "ActorId", null, null, false, SequenceNameOverrides[1]),
				new DbColumnConfiguration(ColumnNames[2], DbType.AnsiString, typeof(string), false, 2, AutoIncrementOverrides[2] ?? false, null, 255, false, false, false, "Application", null, null, false, SequenceNameOverrides[2]),
				new DbColumnConfiguration(ColumnNames[3], DbType.AnsiString, typeof(string), false, 3, AutoIncrementOverrides[3] ?? false, null, 255, false, false, false, "Module", null, null, false, SequenceNameOverrides[3]),
				new DbColumnConfiguration(ColumnNames[4], DbType.AnsiString, typeof(string), true, 4, AutoIncrementOverrides[4] ?? false, null, 255, false, false, false, "Context", null, null, false, SequenceNameOverrides[4]),
				new DbColumnConfiguration(ColumnNames[5], DbType.AnsiString, typeof(string), false, 5, AutoIncrementOverrides[5] ?? false, null, 255, false, false, false, "Component", null, null, false, SequenceNameOverrides[5]),
				new DbColumnConfiguration(ColumnNames[6], DbType.AnsiString, typeof(string), true, 6, AutoIncrementOverrides[6] ?? false, null, 255, false, false, false, "PropertyPathString", null, null, false, SequenceNameOverrides[6]),
				new DbColumnConfiguration(ColumnNames[7], DbType.AnsiString, typeof(string), true, 7, AutoIncrementOverrides[7] ?? false, null, 4000, false, false, false, "Value", null, null, false, SequenceNameOverrides[7]),
				new DbColumnConfiguration(ColumnNames[8], DbType.AnsiString, typeof(string), true, 8, AutoIncrementOverrides[8] ?? false, null, 255, false, false, false, "Description", null, null, false, SequenceNameOverrides[8]),
				new DbColumnConfiguration(ColumnNames[9], DbType.DateTime, typeof(DateTime), false, 9, AutoIncrementOverrides[9] ?? false, null, 0, false, false, false, "ValidFrom", new DateTime(1900, 1, 1), new DateTime(2079, 6, 6), false, SequenceNameOverrides[9]),
				new DbColumnConfiguration(ColumnNames[10], DbType.DateTime, typeof(DateTime), true, 10, AutoIncrementOverrides[10] ?? false, null, 0, false, false, false, "ValidUntil", new DateTime(1900, 1, 1), new DateTime(2079, 6, 6), false, SequenceNameOverrides[10]),
				new DbColumnConfiguration(ColumnNames[11], DbType.Byte, typeof(byte), false, 11, AutoIncrementOverrides[11] ?? false, null, 0, false, false, false, "Status", byte.MinValue, byte.MaxValue, false, SequenceNameOverrides[11]),
			};
        }

        private static DbTableConfiguration CreateImmutableTableProperties()
        {
            return new DbTableConfiguration
            (
                AppSettingsCatalog.GetTableNameOverride("AppSettings") ?? "AppSettings",
                new AppSettingsCatalog(),
                ImmutableColumnProperties,
                new int[] { 0 },
                new string[] { },
                /*is view*/ false
            );
        }

        #endregion

        #region Constructors.

        /// <summary>
        /// Initializes a new instance of AppSettingsMeta class.
        /// </summary>
        public AppSettingsMeta()
            : base(ImmutableTableProperties, null, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of AppSettingsMeta class.
        /// </summary>
        /// <param name="alias">Object alias. If NULL then it will be equal to the table name.</param>
        public AppSettingsMeta(string alias)
            : base(ImmutableTableProperties, alias, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of AppSettingsMeta class.
        /// </summary>
        /// <param name="setPrefixedColumnAliases">Whether to change aliases of all columns so that they start with prefix (usually table name).</param>
        public AppSettingsMeta(bool setPrefixedColumnAliases)
            : base(ImmutableTableProperties, null, setPrefixedColumnAliases)
        {
        }

        /// <summary>
        /// Initializes a new instance of AppSettingsMeta class.
        /// </summary>
        /// <param name="alias">Object alias. If NULL then it will be equal to the table name.</param>
        /// <param name="setPrefixedColumnAliases">Whether to change aliases of all columns so that they start with prefix (usually table name).</param>
        public AppSettingsMeta(string alias, bool setPrefixedColumnAliases)
            : base(ImmutableTableProperties, alias, setPrefixedColumnAliases)
        {
        }

        #endregion

        #region CreateForeignKeys.

        /// <summary>
        /// Initializes an array of relations used by foreign keys.
        /// Only relations to other generated IDbTable classes are created.
        /// </summary>
        protected override DbRelation[] CreateForeignKeys()
        {
            DbRelation[] foreignKeys = new DbRelation[0];

            return foreignKeys;
        }

        #endregion

        #region New* methods.

        /// <summary>
        /// Creates a new AppSettingsEntity object.
        /// </summary>
        /// <returns>New entity.</returns>
        public override IEntity NewEntity()
        {
            return new AppSettingsEntity(this);
        }

        /// <summary>
        /// Creates a new EntityReader&lt;AppSettingsEntity&gt; object.
        /// </summary>
        /// <returns>An instance of EntityReader&lt;AppSettingsEntity&gt; class.</returns>
        public override IObjectReader NewEntityReader()
        {
            // Use default EntityReader<T>() constructor when targeting SQLite database or when column types are compatible/convertible, but do not exactly match, entity property types.
            return new EntityReader<AppSettingsEntity>(AppSettingsEntity.NewEntity);
        }

        #endregion

        #region Clone.

        /// <summary>
        /// Creates another IDbTable object for the same table/view.
        /// </summary>
        /// <param name="cloneAlias">Clone alias.</param>
        /// <returns>Clone.</returns>
        public override IDbTable Clone(string cloneAlias)
        {
            return new AppSettingsMeta(cloneAlias);
        }

        /// <summary>
        /// Creates another IDbTable object for the same table/view.
        /// </summary>
        /// <param name="cloneAlias">Clone alias.</param>
        /// <param name="setPrefixedAliases">Specifies whether cloned columns will have prefixed aliases.</param>
        /// <returns>Clone.</returns>
        public override IDbTable Clone(string cloneAlias, bool setPrefixedAliases)
        {
            return new AppSettingsMeta(cloneAlias, setPrefixedAliases);
        }

        #endregion

        #region Columns.

        /// <summary>
        /// Gets metadata for 'AppSettingId' column.
        /// </summary>
        public IDbColumn AppSettingId
        {
            get { return this.Columns[0]; }
        }

        /// <summary>
        /// Gets metadata for 'ActorId' column.
        /// </summary>
        public IDbColumn ActorId
        {
            get { return this.Columns[1]; }
        }

        /// <summary>
        /// Gets metadata for 'Application' column.
        /// </summary>
        public IDbColumn Application
        {
            get { return this.Columns[2]; }
        }

        /// <summary>
        /// Gets metadata for 'Module' column.
        /// </summary>
        public IDbColumn Module
        {
            get { return this.Columns[3]; }
        }

        /// <summary>
        /// Gets metadata for 'Context' column.
        /// </summary>
        public IDbColumn Context
        {
            get { return this.Columns[4]; }
        }

        /// <summary>
        /// Gets metadata for 'Component' column.
        /// </summary>
        public IDbColumn Component
        {
            get { return this.Columns[5]; }
        }

        /// <summary>
        /// Gets metadata for 'PropertyPathString' column.
        /// </summary>
        public IDbColumn PropertyPathString
        {
            get { return this.Columns[6]; }
        }

        /// <summary>
        /// Gets metadata for 'Value' column.
        /// </summary>
        public IDbColumn Value
        {
            get { return this.Columns[7]; }
        }

        /// <summary>
        /// Gets metadata for 'Description' column.
        /// </summary>
        public IDbColumn Description
        {
            get { return this.Columns[8]; }
        }

        /// <summary>
        /// Gets metadata for 'ValidFrom' column.
        /// </summary>
        public IDbColumn ValidFrom
        {
            get { return this.Columns[9]; }
        }

        /// <summary>
        /// Gets metadata for 'ValidUntil' column.
        /// </summary>
        public IDbColumn ValidUntil
        {
            get { return this.Columns[10]; }
        }

        /// <summary>
        /// Gets metadata for 'Status' column.
        /// </summary>
        public IDbColumn Status
        {
            get { return this.Columns[11]; }
        }

        #endregion

        #region Children.

        /// <summary>
        /// Gets tables which reference the current table.
        /// </summary>
        /// <returns>Array of tables or empty array if the current table is not referenced by other objects.</returns>
        public override IDbTable[] GetChildTables()
        {
            return new IDbTable[]
			{
			};
        }

        /// <summary>
        /// Gets relations where current table acts as a parent.
        /// </summary>
        /// <returns>Array of relations or empty array if the current table is not referenced by other objects.</returns>
        public override DbRelation[] GetChildRelations()
        {
            return new DbRelation[]
			{
			};
        }

        #endregion
    }
}
